var PeerManager = (function () { 
  var localId,
      config = {
        peerConnectionConfig: {
          iceServers: [
            {"url": "stun:23.21.150.121"},
            {"url": "stun:stun.l.google.com:19302"}
          ]
        },
        peerConnectionConstraints: {
          optional: [
            {"DtlsSrtpKeyAgreement": true}
          ]
        }
      },
      peerDatabase = {},
      localStream,
   
      socket = io();
      
  socket.on('message', handleMessage);
  socket.on('id', function(id) {
	  console.log("socket.on");
    localId = id;
  });
      
  function addPeer(remoteId,index) {
    var peer = new Peer(config.peerConnectionConfig, config.peerConnectionConstraints,index,remoteId);
    var hammertime = new Hammer(peer.remoteVideoEl); 
      hammertime.on('tap pan press', function(e) {
        console.log(e);
        var bb = e.target.getBoundingClientRect();
  // Correct, but will not work with touch.
  var position = {
      x: e.pointers[0].layerX,
      y: e.pointers[0].layerY,
  }
  // Correct and works with touch.
  var position2 = {
      x: e.center.x - bb.left,
      y: e.center.y - bb.top,
      type: e.type
  } 
   control(remoteId,position2);
  //PeerManager.control(remoteId,position2);
    
      });
  
	
    peer.pc.onicecandidate = function(event) {
		console.log("peer.pc.onicecandidate");
      if (event.candidate) {
        send('candidate', remoteId, {
          label: event.candidate.sdpMLineIndex,
          id: event.candidate.sdpMid,
          candidate: event.candidate.candidate
        });
      }
    };
    peer.pc.onaddstream = function(event) {
      console.log("peer.pc.onaddstream"); 
      console.log(peer.remoteVideoEl);
		   attachMediaStream(peer.remoteVideoEl, event.stream); 
     
    };
    peer.pc.onremovestream = function(event) {
			console.log("peer.pc.onremovestream");
      peer.remoteVideoEl.src = '';
      
    };
    peer.pc.oniceconnectionstatechange = function(event) {
			console.log(" peer.pc.oniceconnectionstatechange");
      switch(
      (  event.srcElement // Chrome
      || event.target   ) // Firefox
      .iceConnectionState) {
        case 'disconnected': 
          break;
      }
    };
    peerDatabase[remoteId] = peer;
        
    return peer;
  }
  function answer(remoteId) {
    var pc = peerDatabase[remoteId].pc;
    pc.createAnswer(
      function(sessionDescription) {
		  
        pc.setLocalDescription(sessionDescription);
        send('answer', remoteId, sessionDescription);
      }, 
      error
    );
  }
  function offer(remoteId) {
    var pc = peerDatabase[remoteId].pc;
    pc.createOffer(
      function(sessionDescription) {
        pc.setLocalDescription(sessionDescription);
        send('offer', remoteId, sessionDescription);
      }, 
      error
    );
  }
  function control(remoteId,ev){
    console.log('control');
   var pc = peerDatabase[remoteId].pc;
   send('control', remoteId, ev);
 }

  function handleMessage(message) {
    var type = message.type,
        from = message.from,
        pc = (peerDatabase[from] || addPeer(from)).pc;

    console.log('received ' + type + ' from ' + from);
  
    switch (type) {
      case 'init':
        toggleLocalStream(pc);
        offer(from);
        break;
      case 'offer':
        pc.setRemoteDescription(new RTCSessionDescription(message.payload), function(){}, error);
        answer(from);
        break;
      case 'answer':
        pc.setRemoteDescription(new RTCSessionDescription(message.payload), function(){}, error);
        break;
      case 'candidate':
        if(pc.remoteDescription) {
          pc.addIceCandidate(new RTCIceCandidate({
            sdpMLineIndex: message.payload.label,
            sdpMid: message.payload.id,
            candidate: message.payload.candidate
          }), function(){}, error);
        }
        break;
    }
  }
  function send(type, to, payload) {
    console.log('sending ' + type + ' to ' + to);

    socket.emit('message', {
      to: to,
      type: type,
      payload: payload
    });
  }
  function toggleLocalStream(pc) {
    if(localStream) {
      (!!pc.getLocalStreams().length) ? pc.removeStream(localStream) : pc.addStream(localStream);
    }
  }
  function error(err){
    console.log(err);
  }

  return {
    getId: function() {
      return localId;
    }, 
 
    peerInit: function(remoteId,index) {
		console.log('peerInit');
      peer = peerDatabase[remoteId] || addPeer(remoteId,index);
      send('init', remoteId, null);
    },
    
    peerRenegociate: function(remoteId) {
      offer(remoteId);
    },

    send: function(type, payload) {
      socket.emit(type, payload);
    }
  };
  
});

var Peer = function (pcConfig, pcConstraints,index,remoteId) {
	console.log(index);
  this.pc = new RTCPeerConnection(pcConfig, pcConstraints); 
    this.remoteVideoEl = document.getElementById('video'+index);   
 
}